package com.uinnova.product.eam.workable.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.uinnova.product.eam.feign.workable.entity.*;
import com.uinnova.product.eam.workable.dto.WorkBenchMessageDto;
import com.uinnova.product.eam.workable.model.ActRuTask;
import com.uinnova.product.eam.workable.model.FilterUser;
import com.uinnova.product.eam.workable.model.Terminate;
import com.uinnova.product.eam.workable.repository.ActRuTaskRepository;
import com.uinnova.product.eam.workable.rsm.RsmUtils;
import com.uinnova.product.eam.workable.util.HttpUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.flowable.bpmn.constants.BpmnXMLConstants;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.common.engine.impl.db.SuspensionState;
import org.flowable.common.engine.impl.identity.Authentication;
import org.flowable.engine.*;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.repository.DeploymentBuilder;
import org.flowable.engine.runtime.ActivityInstance;
import org.flowable.engine.runtime.Execution;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.image.ProcessDiagramGenerator;
import org.flowable.task.api.Task;
import org.flowable.task.api.TaskInfo;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.flowable.variable.api.history.HistoricVariableInstance;
import org.flowable.variable.api.persistence.entity.VariableInstance;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.stream.Collectors;
import java.util.zip.ZipInputStream;

/**
 * flowable基础服务层
 * flowable-modeler地址：http://109IP:8080/flowable-modeler
 *
 * @author lichong
 * @since 2022/2/22 11:32
 */
@Slf4j
@Service
public class FlowableService {

    @Resource
    private TerminateService terminateService;

    @Resource
    private RuntimeService runtimeService;

    @Resource
    private TaskService taskService;

    @Resource
    private HistoryService historyService;

    @Resource
    private RepositoryService repositoryService;

    @Resource
    private ProcessEngine processEngine;

    @Value("${http.resource.space}")
    private String httpResouceUrl;

    @Value("${local.resource.space}")
    private String localPath;

    @Value("${generic.user.url}")
    private String genericUserUrl;

    @Resource
    private FilterUserService filterUserService;

    @Value("${eam.message.change.url:http://ip/tarsier-eam/eam/workbenchChargeDone/changeAction}")
    private String eamMessageChangeUrl;

    @Value("${eam.message.save.url:http://ip/tarsier-eam/eam/workbenchChargeDone/saveOrUpdate}")
    private String eamMessageSaveUrl;

    @Resource
    private HttpUtil httpUtil;

    @Autowired
    private RsmUtils rsmUtils;

    @Resource
    private ActRuTaskRepository actRuTaskRepository;

    private static final String planProcessDefineKey = "xw_it_technical_approve";

    public static final String PLAN_DEFINITION_KEY1 = "cj_technical_scheme_approve";

    public static final String MODEL_DEFINITION_KEY = "xw_model_approve";

    public static final String XW_BUSINESS_SCENARIO_APPROVE = "xw_business_scenario_approve";
    private static final String viewProcessDefineKey = "xw_it_diagram_approve";
    private static final String GT_TECHNICAL_SCHEME_APPROVE = "guotou_technical_scheme_approve_with_sub";
    private static final String GT_DIAGRAM_APPROVE = "guotou_diagram_approve";
    private static final String GT_ASSERT_APPROVE = "guotou_assert_approve";

    /**
     * 部署流程定义
     *
     * @param processDefinitionName          定义名字
     * @param bpmnProcessDefinitionName      流程文件名称
     * @param bpmnProcessDefinition          流程文件流
     * @param bpmnProcessDefinitionImageName 流程图片名称
     * @param bpmnProcessDefinitionImage     流程图片文件流
     * @return 流程定义信息
     */
    public Deployment deployProcessDefinition(String processDefinitionName, String bpmnProcessDefinitionName
            , InputStream bpmnProcessDefinition, String bpmnProcessDefinitionImageName
            , InputStream bpmnProcessDefinitionImage) {
        DeploymentBuilder deploymentBuilder = repositoryService.createDeployment()
                .name(processDefinitionName)
                .addInputStream(bpmnProcessDefinitionName, bpmnProcessDefinition);
        if (bpmnProcessDefinitionImageName != null && bpmnProcessDefinitionImage != null) {
            deploymentBuilder.addInputStream(bpmnProcessDefinitionImageName, bpmnProcessDefinitionImage);
        }
        return deploymentBuilder.deploy();
    }

    /**
     * 部署流程定义
     *
     * @param processDefinitionName    定义名字
     * @param bpmnProcessDefinitionZip zip包
     * @return 流程定义信息
     */
    public Deployment deployProcessDefinitionZip(String processDefinitionName, ZipInputStream bpmnProcessDefinitionZip) {
        return repositoryService.createDeployment()
                .name(processDefinitionName)
                .addZipInputStream(bpmnProcessDefinitionZip).deploy();
    }

    /**
     * 发起流程
     *
     * @param processDefinitionKey 流程定义key
     * @param variables            全局变量
     * @return
     */
    public ProcessInstance startProcess(String owner, String processDefinitionKey, String businessKey, String processInstanceName, Map<String, Object> variables) {
        if (StringUtils.isNotBlank(businessKey)) {
            ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceBusinessKey(businessKey, processDefinitionKey).singleResult();
            if (processInstance != null) {
                return processInstance;
            }
        }
        //设置流程发起人
        Authentication.setAuthenticatedUserId(owner);
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinitionKey, businessKey, variables);
        if (StringUtils.isNotBlank(processInstanceName)) {
            runtimeService.setProcessInstanceName(processInstance.getProcessInstanceId(), processInstanceName);
        }
        return processInstance;
    }

    /**
     * 发起流程并绑定用户
     *
     * @param processRequest 流程信息
     * @return
     */
    public Task startProcessBindAssignee(ProcessRequest processRequest) {
        Map<String, Object> routerVariables = processRequest.getRouterVariables();
        if (!CollectionUtils.isEmpty(processRequest.getChildProcessRequestList())) {
            routerVariables.put("activeChildProcess", "true");
            List<String> childVariableList = new ArrayList<>();
            List<ChildProcessRequest> childProcessRequestList = processRequest.getChildProcessRequestList();
            for (ChildProcessRequest childProcessRequest : childProcessRequestList) {
                String childBusinessKey = childProcessRequest.getChildBusinessKey();
                Map<String, Object> childVariable = childProcessRequest.getChildVariable();
                childVariable.put("childBusinessKey", childBusinessKey);
                childVariableList.add(JSON.toJSONString(childVariable));
            }
            routerVariables.put("childVariableList", childVariableList);
        } else {
            routerVariables.put("activeChildProcess", "false");
        }
        ProcessInstance processInstance = startProcess(processRequest.getOwner(), processRequest.getProcessDefinitionKey()
                , processRequest.getBusinessKey(), processRequest.getProcessInstanceName(), processRequest.getRouterVariables());
        Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
        //发起后第一节点绑定自己
        task.setAssignee(processRequest.getUserId());
        taskService.setAssignee(task.getId(), processRequest.getUserId());
        sendTaskMessage(Collections.singletonList(task), true);
        terminateService.deleteTerminate(processRequest.getBusinessKey(), processRequest.getProcessDefinitionKey());
        return task;
    }

    /**
     * 根据流程定义key查询所有流程实例
     *
     * @param processDefinitionKey
     * @return
     */
    public List<ProcessInstance> getProcessInstanceByprocessDefinitionKey(String processDefinitionKey) {
        return runtimeService.createProcessInstanceQuery().processDefinitionKey(processDefinitionKey).list();
    }

    /**
     * 获取指定用户组流程任务列表
     *
     * @param group
     * @return
     */
    public List<TaskResponse> getTaskListByGroup(String group) {
        List<Task> list = taskService.createTaskQuery().taskCandidateGroup(group).list();
        return getTaskResponses(list);
    }

    /**
     * 获取指定用户组流程任务列表
     *
     * @param groups
     * @return
     */
    public List<TaskResponse> getTaskListByGroups(List<String> groups) {
        List<Task> list = taskService.createTaskQuery().taskCandidateGroupIn(groups).list();
        return getTaskResponses(list);
    }


    public List<TaskResponse> getTaskListByProcessInstanceId(String processInstanceId) {
        List<Task> list = taskService.createTaskQuery().processInstanceId(processInstanceId).list();
        return getTaskResponses(list);
    }

    /**
     * 获取代办列表（分页）
     *
     * @param userId 用户id
     * @return 任务列表返回体
     */
    public PageEntityInfo<TaskResponse> getTaskResponseListByUser(String userId, Integer pageNum, Integer pageSize) {
        if (pageNum == null || pageNum < 1) {
            pageNum = 1;
        }
        if (pageSize == null) {
            pageSize = 10;
        } else if (pageSize > 500) {
            pageSize = 500;
        }
        long count = taskService.createTaskQuery()
                .taskAssignee(userId).count();
        long pages = (count + pageSize - 1) / pageSize;
        List<Task> list = taskService.createTaskQuery().taskAssignee(userId)
                .orderByTaskCreateTime()
                .desc()
                .listPage((pageNum - 1) * pageSize, pageSize);
        PageEntityInfo<TaskResponse> taskResponsePageEntityInfo = new PageEntityInfo<>();
        List<TaskResponse> taskResponses = getTaskResponses(list);
        taskResponsePageEntityInfo.setList(taskResponses);
        taskResponsePageEntityInfo.setPageNum(pageNum);
        taskResponsePageEntityInfo.setPageSize(pageSize);
        taskResponsePageEntityInfo.setPages(pages);
        taskResponsePageEntityInfo.setTotal(count);
        return taskResponsePageEntityInfo;
    }

    /**
     * 获取已办列表（分页）
     *
     * @param userId
     * @param pageSize
     * @param pageNum
     * @return
     */
    public PageEntityInfo<TaskResponse> getDoneTaskListByUserId(String userId, Integer pageSize, Integer pageNum) {
        if (pageNum == null || pageNum < 1) {
            pageNum = 1;
        }
        if (pageSize == null) {
            pageSize = 10;
        } else if (pageSize > 500) {
            pageSize = 500;
        }
        //TODO 过滤系统自动停止的任务 模糊搜索 pass noPass cancel人工处理的已办任务
        long count = historyService.createHistoricTaskInstanceQuery()
                .taskAssignee(userId).taskVariableValueLikeIgnoreCase("pass","%a%").finished().count();
        long pages = (count + pageSize - 1) / pageSize;
        List<HistoricTaskInstance> historicTaskInstanceList = historyService.createHistoricTaskInstanceQuery()
                .taskAssignee(userId)
                .orderByHistoricTaskInstanceEndTime()
                .taskVariableValueLikeIgnoreCase("pass","%a%")
                .finished()
                .desc()
                .listPage((pageNum - 1) * pageSize, pageSize);
        List<TaskResponse> doneTaskResponses = getDoneTaskResponses(historicTaskInstanceList);
        PageEntityInfo<TaskResponse> taskResponsePageEntityInfo = new PageEntityInfo<>();
        taskResponsePageEntityInfo.setList(doneTaskResponses);
        taskResponsePageEntityInfo.setPageNum(pageNum);
        taskResponsePageEntityInfo.setPageSize(pageSize);
        taskResponsePageEntityInfo.setTotal(count);
        taskResponsePageEntityInfo.setPages(pages);
        return taskResponsePageEntityInfo;
    }

    public List<TaskResponse> getDoneTaskList(String userId, List<String> processInstanceIds) {
        //过滤系统自动停止的任务 模糊搜索 pass noPass cancel人工处理的已办任务
        List<HistoricTaskInstance> historicTaskInstanceList = historyService.createHistoricTaskInstanceQuery()
                .taskAssignee(userId)
                .processInstanceIdIn(processInstanceIds)
                .orderByHistoricTaskInstanceEndTime()
                .taskVariableValueLikeIgnoreCase("pass","%a%")
                .finished()
                .desc()
                .list();
        return getDoneTaskResponses(historicTaskInstanceList);
    }

    /**
     * 完成任务（通过/拒绝）
     *
     * @param taskRequest 请求参数
     * @return
     */
    public TaskResponse completeTask(TaskRequest taskRequest) {
        Task task = taskService.createTaskQuery().taskId(taskRequest.getTaskId()).singleResult();
        if (task == null) {
            log.info("该任务已结束");
            //兼容任务重复提交的问题
            TaskResponse taskResponse = new TaskResponse();
            taskResponse.setProcessEnd(Boolean.TRUE);
            return taskResponse;
        }
        String processInstanceId = task.getProcessInstanceId();
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        //variables存放流程路由使用的变量
        Map<String, Object> routerVariables = taskRequest.getRouterVariables();
        if (routerVariables == null) {
            routerVariables = new HashMap<>();
        }

        if (!CollectionUtils.isEmpty(taskRequest.getChildProcessRequestList())) {
            routerVariables.put("activeChildProcess", "true");
            List<String> childVariableList = new ArrayList<>();
            List<ChildProcessRequest> childProcessRequestList = taskRequest.getChildProcessRequestList();
            for (ChildProcessRequest childProcessRequest : childProcessRequestList) {
                String childBusinessKey = childProcessRequest.getChildBusinessKey();
                Map<String, Object> childVariable = childProcessRequest.getChildVariable();
                childVariable.put("childBusinessKey", childBusinessKey);
                childVariableList.add(JSON.toJSONString(childVariable));
            }
            routerVariables.put("childVariableList", childVariableList);
        } else {
            routerVariables.put("activeChildProcess", "false");
        }

        //localVariables用于存放历史查询时的变量
        Map<String, Object> taskEchoVariables = taskRequest.getTaskEchoVariables();

        if (CollectionUtils.isEmpty(taskEchoVariables)) {
            taskEchoVariables = new HashMap<>();
            taskEchoVariables.put("remarks", taskRequest.getRemarks());
        } else {
            taskEchoVariables.put("remarks", taskRequest.getRemarks());
        }

        taskEchoVariables.put("curTaskId", taskRequest.getTaskId());

        //会签多用户处理
        if (StringUtils.isNotBlank(taskRequest.getNextUserIds())) {
            String[] split = taskRequest.getNextUserIds().split(",");
            //兼容单人会签
            if (split.length > 0) {
                HashSet<String> users = Sets.newHashSet(split);
                routerVariables.put("assigneeList", users);
            }
        }
        //获取当前任务定义key
        String taskDefinitionKey = task.getTaskDefinitionKey();
        if (FLOWACTION.ACCETP.toString().equals(taskRequest.getAction().toString())) {
            taskEchoVariables.put("pass", "pass");
            routerVariables.put("goOut", "pass");
            if (taskRequest.getFilterUser()) {
                addUserFilter(processInstanceId, task.getAssignee());
            }
        }else if(FLOWACTION.CANCEL.toString().equals(taskRequest.getAction().toString())){
            taskEchoVariables.put("pass", "cancel");
            Terminate terminate = new Terminate();
            terminate.setBusinessKey(processInstance.getBusinessKey());
            terminate.setProcessDefinitionKey(processInstance.getProcessDefinitionKey());
            terminateService.saveTerminate(terminate);
        } else if(FLOWACTION.REJECT.toString().equals(taskRequest.getAction().toString())){
            taskEchoVariables.put("pass", "noPass");
        }else if(FLOWACTION.RECALL.toString().equals(taskRequest.getAction().toString())){
            taskEchoVariables.put("pass", "recall");
        }else if(FLOWACTION.REJECT_INIT_OWNER.toString().equals(taskRequest.getAction().toString())){
            taskEchoVariables.put("pass", "rejectInitOwner");
        }else {
            taskEchoVariables.put("pass", "noAgree");
        }
        taskEchoVariables.put("user", task.getAssignee());
        //设置任务数据，可通过任务id查到任务临时数据
        taskService.setVariablesLocal(taskRequest.getTaskId(), taskEchoVariables);
        try {
            taskService.complete(taskRequest.getTaskId(), routerVariables, taskEchoVariables);
            //将代办变为已办
            changeToDoneMessage(taskRequest.getTaskId());
        } catch (NullPointerException e) {
            //throw new RuntimeException("请配置审批角色和用户!");
            TaskResponse taskResponse = new TaskResponse();
            taskResponse.setErrorCode(60001);
            return taskResponse;
        }
        //查询任务数量，可能单任务可能多任务。需要用taskDefinitionKey是否相同来判断
        List<Task> taskList = taskService.createTaskQuery().processInstanceId(processInstanceId).list();
        int count = taskList.size();
        TaskResponse taskResponse = new TaskResponse();
        taskResponse.setProcessInstanceId(processInstanceId);
        taskResponse.setBusinessKey(processInstance.getBusinessKey());
        taskResponse.setProcessDefinitionKey(processInstance.getProcessDefinitionKey());
        if (count == 1) {
            Task task1 = taskList.get(0);
            String nextTaskDefinitionKey = task1.getTaskDefinitionKey();
            //判断是否是多实例任务,多实例任务的定义key一样
            if (!taskDefinitionKey.equals(nextTaskDefinitionKey)) {
                //单任务处理
                //如果有下一个任务，设置下个任务的领取人
                Task nextTask = taskService.createTaskQuery().processInstanceId(processInstanceId).singleResult();
                if (nextTask != null) {
                    String assignee = nextTask.getAssignee();
                    //若图上设置节点为发起人则不设置用户
                    if ("$INITIATOR".equals(assignee)) {
                        taskService.setAssignee(nextTask.getId(), processInstance.getStartUserId());
                    } else if (assignee == null) {
                        //没设置就给当前任务领取人
                        if (StringUtils.isNotBlank(taskRequest.getNextUserIds())) {
                            taskService.setAssignee(nextTask.getId(), taskRequest.getNextUserIds());
                        } else {
                            taskService.setAssignee(nextTask.getId(), task.getAssignee());
                        }
                    }
                }
            } else {
                //多实例任务不能更改领取人
                log.info("多实例任务，不设置领取人");
            }
            taskResponse.setTaskId(task1.getId());
        } else if (count > 1) {
            //子流程存在的情况被驳回后会查询到别人的任务，所以需要改一下
            for (Task task1 : taskList) {
                String assignee = task1.getAssignee();
                if ("$INITIATOR".equals(assignee)) {
                    taskService.setAssignee(task1.getId(), processInstance.getStartUserId());
                }
            }
        } else {
            log.info("{}---{}流程结束", processInstanceId, processInstance.getName());
            taskResponse.setProcessEnd(Boolean.TRUE);
            String processDefinitionKey = processInstance.getProcessDefinitionKey();
            //若是技术方案审批流程结束则需要删除流程中的过滤用户
            if ("cj_technical_scheme_approve".equals(processDefinitionKey)) {
                filterUserService.deleteFilterUserByProcessInstanceId(processInstanceId);
            }
        }
        taskList = taskService.createTaskQuery().processInstanceId(processInstanceId).list();
        // 生成代办信息，会签会存在重复任务，需要消息阶段做下幂等性处理
        sendTaskMessage(taskList, false);
        return taskResponse;
    }

    /**
     * 查看历史流程记录
     * @param processInstanceId
     * @return
     */
    public List<HistoricActivityInstance> getHistoryList(String processInstanceId) {
        return historyService.createHistoricActivityInstanceQuery()
                .processInstanceId(processInstanceId).finished().orderByHistoricActivityInstanceEndTime().asc().list();
    }

    /**
     * 驳回流程实例
     * @param taskId
     * @param targetTaskKey
     * @return
     */
    public void rollbaskTask(String taskId, String targetTaskKey) {
        Task currentTask = taskService.createTaskQuery().taskId(taskId).singleResult();
        if (currentTask == null) {
            throw new RuntimeException("节点不存在");
        }
        List<String> key = new ArrayList<>();
        key.add(currentTask.getTaskDefinitionKey());
        runtimeService.createChangeActivityStateBuilder()
                .processInstanceId(currentTask.getProcessInstanceId())
                .moveActivityIdsToSingleActivityId(key, targetTaskKey)
                .changeState();
    }

    /**
     * 终止流程实例
     *
     * @param processBusinessId 业务主键
     * @param deleteReason      删除原因
     */
    public void deleteProcessBusinessId(String processBusinessId, String deleteReason) {
        if (StringUtils.isEmpty(deleteReason)) {
            deleteReason = "";
        }
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceBusinessKey(processBusinessId).singleResult();
        if (processInstance != null) {
            runtimeService.deleteProcessInstance(processInstance.getProcessInstanceId(), deleteReason);
        }
    }

    /**
     * 终止流程实例
     *
     * @param processInstanceId 流程实例id
     * @param deleteReason      删除原因
     */
    public void deleteProcessInstanceById(String processInstanceId, String deleteReason) {
        if (StringUtils.isEmpty(deleteReason)) {
            deleteReason = "";
        }
        runtimeService.deleteProcessInstance(processInstanceId, deleteReason);
    }

    /**
     * 删除历史流程实例
     *
     * @param processInstanceId
     */
    public void deleteHistoryProcessInstanceById(String processInstanceId) {
        HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        if(historicProcessInstance!=null){
            historyService.deleteHistoricProcessInstance(processInstanceId);
        }
    }

    /**
     * 挂起流程实例
     *
     * @param processInstanceId 当前流程实例id
     */
    public void handUpProcessInstance(String processInstanceId) {
        runtimeService.suspendProcessInstanceById(processInstanceId);
    }

    /**
     * 恢复（唤醒）被挂起的流程实例
     *
     * @param processInstanceId 流程实例id
     */
    public String activateProcessInstance(String processInstanceId) {
        runtimeService.activateProcessInstanceById(processInstanceId);
        return "恢复流程成功...";
    }

    /**
     * 判断传入流程实例在运行中是否存在
     *
     * @param processInstanceId
     * @return
     */
    public Boolean isExistProcIntRunning(String processInstanceId) {
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        return processInstance != null;
    }

    /**
     * 判断流程实例在历史记录中是否存在
     *
     * @param processInstanceId
     * @return
     */
    public Boolean isExistProcInHistory(String processInstanceId) {
        HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        return historicProcessInstance != null;
    }

    /**
     * 我发起的流程实例列表
     *
     * @param userId 用户id
     * @return 流程实例列表
     */
    public List<HistoricProcessInstance> getMyStartProcint(String userId) {
        List<HistoricProcessInstance> list = historyService
                .createHistoricProcessInstanceQuery()
                .startedBy(userId)
                .orderByProcessInstanceStartTime()
                .asc()
                .list();
        return list;
    }

    /**
     * 查询流程图
     *
     * @param processId
     * @return 图片的文件流
     * @throws Exception
     */
    public String genProcessDiagramByProcessId(String processId) {
        HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processId).singleResult();
        //流程走完的不显示图
        if (historicProcessInstance == null) {
            return null;
        }
        return genProcessDiagram(processId, historicProcessInstance.getProcessDefinitionId());
    }

    public List<HistoryTaskResponse> getHistoryTaskDataByPorcessInstanceId(String processInstanceId) {


        HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
                .processInstanceId(processInstanceId)
                .singleResult();
        String startUserId = historicProcessInstance.getStartUserId();
        List<HistoricTaskInstance> historicTaskInstanceList = historyService.createHistoricTaskInstanceQuery()
                .processInstanceId(processInstanceId)
                .orderByHistoricTaskInstanceEndTime()
                .asc()
                .finished()
                .list();
        List<HistoricVariableInstance> historicVariableInstanceList = historyService.createHistoricVariableInstanceQuery()
                .processInstanceId(processInstanceId)
                .list();
        HashMap<String, Map<String, Object>> tmpMap = Maps.newHashMap();
        for (HistoricVariableInstance historicVariableInstance : historicVariableInstanceList) {
            if (historicVariableInstance.getTaskId() != null) {
                Map<String, Object> historicVariableMap = tmpMap.get(historicVariableInstance.getTaskId());
                if (historicVariableMap == null) {
                    historicVariableMap = new HashMap<>();
                }
                historicVariableMap.put(historicVariableInstance.getVariableName(), historicVariableInstance.getValue());
                tmpMap.put(historicVariableInstance.getTaskId(), historicVariableMap);
            }
        }
        List<HistoryTaskResponse> historyTaskResponseList = Lists.newArrayList();
        boolean gtArchReview = GT_TECHNICAL_SCHEME_APPROVE.equals(historicProcessInstance.getProcessDefinitionKey());
        boolean gtDiagramApprove = GT_DIAGRAM_APPROVE.equals(historicProcessInstance.getProcessDefinitionKey());
        for (HistoricTaskInstance historicTaskInstance : historicTaskInstanceList) {
            HistoryTaskResponse historyTaskResponse = new HistoryTaskResponse();
            historyTaskResponse.setTaskId(historicTaskInstance.getId());
            historyTaskResponse.setTaskName(historicTaskInstance.getName());
            historyTaskResponse.setCommitTime(historicTaskInstance.getEndTime());
            historyTaskResponse.setUserId(historicTaskInstance.getAssignee());
            historyTaskResponse.setDescription(historicTaskInstance.getDescription());
            Map<String, Object> variablesMap = tmpMap.get(historicTaskInstance.getId());
            //特殊处理下国投架构评审终止/会签自动关闭任务
            if (gtArchReview) {
                archReviewTask(variablesMap, historicTaskInstance, historyTaskResponse);
                if (!CollectionUtils.isEmpty(historyTaskResponse.getVariables())) {
                    historyTaskResponseList.add(historyTaskResponse);
                }
                continue;
            }
            //特殊处理下国投视图审批终止/会签自动关闭任务
            if (gtDiagramApprove) {
                gtDiagramApproveTask(variablesMap, historicTaskInstance, historyTaskResponse);
                historyTaskResponseList.add(historyTaskResponse);
                continue;
            }
            if (variablesMap == null||variablesMap.get("pass")==null) {
                //这种情况是会签过程中，一个人拒绝就决策略，有一个人拒绝了，另一个人任务就没有了，故应该在流程中去掉
                continue;
            }
            String category = historicTaskInstance.getCategory();
            if (StringUtils.equalsIgnoreCase("submit",category)&&startUserId.equals(historicTaskInstance.getAssignee()) && "pass".equals(variablesMap.get("pass"))) {
                variablesMap.put("pass", "submit");
            }
            historyTaskResponse.setVariables(variablesMap);
            String name = historicProcessInstance.getName();
            Object childVariable = variablesMap.get("childVariable");
            if(childVariable!=null){
                JSONObject jsonObject = JSON.parseObject(childVariable.toString());
                String processInstanceName = jsonObject.getString("processInstanceName");
                if(StringUtils.isNotBlank(processInstanceName)){
                    historyTaskResponse.setProcessInstanceName(name+"（"+processInstanceName+"）");
                }else {
                    historyTaskResponse.setProcessInstanceName(name);
                }
            }else {
                historyTaskResponse.setProcessInstanceName(name);
            }
            historyTaskResponseList.add(historyTaskResponse);
        }
        return historyTaskResponseList;
    }

    private void archReviewTask(Map<String, Object> variablesMap, HistoricTaskInstance historicTaskInstance, HistoryTaskResponse historyTaskResponse) {
        if (variablesMap == null) {
            variablesMap = new HashMap<>();
        }
        if (StringUtils.isNotBlank(historicTaskInstance.getDeleteReason())) {
            //或签任务处理后，剩余未处理的任务
            if ("MI_END".equals(historicTaskInstance.getDeleteReason())) {
                variablesMap.put("pass", "autoCLose");
                variablesMap.put("user", historicTaskInstance.getAssignee());
                variablesMap.put("remarks", "");
                variablesMap.put("closeType", "orSignClose");
            } else if (historicTaskInstance.getDeleteReason().contains("terminate end event")) {
                //子流程申请人撤销后，其他未执行任务
                variablesMap.put("pass", "autoCLose");
                variablesMap.put("user", historicTaskInstance.getAssignee());
                variablesMap.put("closeType", "submitterCancel");
            } else {
                //管理员终止
                variablesMap.put("pass", "autoCLose");
                variablesMap.put("user", historicTaskInstance.getAssignee());
                variablesMap.put("remarks", historicTaskInstance.getDeleteReason());
                variablesMap.put("closeType", "adminTerminal");
            }
        }
        if ("startUserSubmit".equals(historicTaskInstance.getDescription())) {
            variablesMap.put("pass", "submit");
        }
        historyTaskResponse.setVariables(variablesMap);
        historyTaskResponse.setProcessInstanceName(historicTaskInstance.getName());
        Object childVariable = variablesMap.get("childVariable");
        if (childVariable != null) {
            JSONObject val = JSON.parseObject(childVariable.toString());
            if (StringUtils.isNotBlank(val.getString("group"))) {
                String taskName = historicTaskInstance.getName();
                taskName = taskName.concat("（").concat(val.getString("group")).concat("-").concat(val.getString("domainName")).concat("）");
                historyTaskResponse.setTaskName(taskName);
            }
            if (StringUtils.isNotBlank(val.getString("finalNodes"))) {
                String taskName = historicTaskInstance.getName();
                taskName = taskName.concat("（").concat(val.getString("domainName").concat("）"));
                historyTaskResponse.setTaskName(taskName);
            }
        }
    }

    private void gtDiagramApproveTask(Map<String, Object> variablesMap, HistoricTaskInstance historicTaskInstance, HistoryTaskResponse historyTaskResponse) {
        if (variablesMap == null) {
            variablesMap = new HashMap<>();
        }
        if (StringUtils.isNotBlank(historicTaskInstance.getDeleteReason())) {
            //会签任务处理后，剩余未处理的任务
            if ("MI_END".equals(historicTaskInstance.getDeleteReason())) {
                variablesMap.put("pass", "autoCLose");
                variablesMap.put("user", historicTaskInstance.getAssignee());
                variablesMap.put("remarks", "");
            } else {
                //管理员终止
                variablesMap.put("pass", "autoCLose");
                variablesMap.put("user", historicTaskInstance.getAssignee());
                variablesMap.put("remarks", historicTaskInstance.getDeleteReason());
            }
        }
        if ("startUserSubmit".equals(historicTaskInstance.getDescription())) {
            variablesMap.put("pass", "submit");
        }
        historyTaskResponse.setVariables(variablesMap);
        historyTaskResponse.setProcessInstanceName(historicTaskInstance.getName());
    }

    public TaskResponse getCurrentTaskAssignees(String businessKey, String processDefinitionKey) {
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                .processInstanceBusinessKey(businessKey)
                .processDefinitionKey(processDefinitionKey)
                .singleResult();
        TaskResponse taskResponse = new TaskResponse();
        if (processInstance == null) {
            log.info("流程已结束");
            return taskResponse;
        }
        List<Task> taskList = taskService.createTaskQuery().processInstanceId(processInstance.getProcessInstanceId()).list();
        List<String> assigneeList = taskList.stream().map(Task::getAssignee).collect(Collectors.toList());
        taskResponse.setCurrentAssignees(StringUtils.join(assigneeList, ","));
        taskResponse.setSubmitter(processInstance.getStartUserId());
        return taskResponse;
    }

    private String genProcessDiagram(String processInstanceId, String processDefinitionId) {
        List<Execution> executions = runtimeService
                .createExecutionQuery()
                .processInstanceId(processInstanceId)
                .list();
        //得到正在执行的Activity的Id
        List<HistoricActivityInstance> historyList = getHistoryList(processInstanceId);
        List<String> activityIds = new ArrayList<>();
        List<String> flows = new ArrayList<>();
        for (HistoricActivityInstance historicActivityInstance : historyList) {
            String activityType = historicActivityInstance.getActivityType();
            if (activityType.equals("sequenceFlow") || activityType.equals("exclusiveGateway")) {
                flows.add(historicActivityInstance.getActivityId());
            }
//            else if (activityType.equals("userTask") || activityType.equals("startEvent")) {
//                activityIds.add(historicActivityInstance.getActivityId());
//            }
        }
        for (Execution exe : executions) {
            List<String> ids = runtimeService.getActiveActivityIds(exe.getId());
            activityIds.addAll(ids);
        }
        //获取流程图
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
        ProcessEngineConfiguration engconf = processEngine.getProcessEngineConfiguration();
        ProcessDiagramGenerator diagramGenerator = engconf.getProcessDiagramGenerator();
        InputStream fileInputStream = diagramGenerator.generateDiagram(bpmnModel, "png"
                , activityIds, flows, engconf.getActivityFontName()
                , engconf.getLabelFontName(), engconf.getAnnotationFontName()
                , engconf.getClassLoader(), 1.0, true);
        String localFilePath = localPath + File.separator + "processDiagram" + File.separator;
        File file = new File(localFilePath);
        if (!file.exists()) {
            boolean mkdirs = file.mkdirs();
            if (!mkdirs) {
                throw new RuntimeException("文件夹创建失败");
            }
        }
        String localFileName = localFilePath + processInstanceId + ".png";
        String httpFilePath = httpResouceUrl + File.separator + "processDiagram" + File.separator + processInstanceId + ".png";
        try (FileOutputStream fileOutputStream = new FileOutputStream(localFileName)) {
            IOUtils.copy(fileInputStream, fileOutputStream);
            rsmUtils.uploadRsmFromFile(new File(localFileName));
        } catch (IOException ioException) {
            log.error("文件生成失败", ioException);
        }
        return httpFilePath;
    }

    private List<TaskResponse> getTaskResponses(List<Task> taskList) {
        Set<String> processInstanceIds = taskList.stream().map(TaskInfo::getProcessInstanceId).collect(Collectors.toSet());
        if (CollectionUtils.isEmpty(processInstanceIds)) {
            return new ArrayList<>(0);
        }
        List<ProcessInstance> list = runtimeService.createProcessInstanceQuery().processInstanceIds(processInstanceIds).list();
        Map<String, ProcessInstance> processInstanceHashMap = new HashMap<>();
        for (ProcessInstance processInstance : list) {
            processInstanceHashMap.put(processInstance.getProcessInstanceId(), processInstance);
        }
        //查询流程当前审批人
        Map<String, List<String>> currentAssigneeMap = getProcessCurrentUser(new ArrayList<>(processInstanceIds));

        Map<String, Map<String, Object>> taskVariablesLocal = new HashMap<>();
        Set<String> taskIds = taskList.stream().map(Task::getId).filter(Objects::nonNull).collect(Collectors.toSet());
        if (!CollectionUtils.isEmpty(taskIds)) {
            List<VariableInstance> variableInstances = taskService.getVariableInstancesLocalByTaskIds(taskIds);
            if (!CollectionUtils.isEmpty(variableInstances)) {
                for (VariableInstance variableInstance : variableInstances) {
                    Map<String, Object> variablesLocal = taskVariablesLocal.getOrDefault(variableInstance.getTaskId(), new HashMap<>());
                    variablesLocal.put(variableInstance.getName(), variableInstance.getValue());
                    taskVariablesLocal.put(variableInstance.getTaskId(), variablesLocal);
                }
            }
        }

        return taskList.stream().filter(tt -> !tt.isSuspended()).parallel().map(t -> {
            Map<String, Object> variablesLocal = taskVariablesLocal.getOrDefault(t.getId(), new HashMap<>());
            TaskResponse taskResponse = new TaskResponse();
            taskResponse.setTaskId(t.getId());
            taskResponse.setProcessInstanceId(t.getProcessInstanceId());
            taskResponse.setProcessDefinitionKey(processInstanceHashMap.get(t.getProcessInstanceId()).getProcessDefinitionKey());
            taskResponse.setTaskDefinitionKey(t.getTaskDefinitionKey());
            taskResponse.setDescription(t.getDescription());
            taskResponse.setTaskCreateTime(t.getCreateTime());
            Object childVariable = variablesLocal.get("childVariable");
            String taskName = t.getName();
            if(childVariable!=null){
                JSONObject jsonObject = JSON.parseObject(childVariable.toString());
                String processInstanceName = processInstanceHashMap.get(t.getProcessInstanceId()).getName();
                if (StringUtils.isNotBlank(jsonObject.getString("processInstanceName"))) {
                    processInstanceName = processInstanceName.concat("（" + jsonObject.getString("processInstanceName") + "）");
                }
                taskResponse.setProcessInstanceName(processInstanceName);
                if (StringUtils.isNotBlank(jsonObject.getString("group"))) {
                    taskName = taskName.concat("（").concat(jsonObject.getString("group")).concat("-").concat(jsonObject.getString("domainName")).concat("）");
                }
                if (StringUtils.isNotBlank(jsonObject.getString("finalNodes"))) {
                    taskName = taskName.concat("（").concat(jsonObject.getString("domainName")).concat("）");
                }
            }else {
                taskResponse.setProcessInstanceName(processInstanceHashMap.get(t.getProcessInstanceId()).getName());
            }
            taskResponse.setTaskName(taskName);
            taskResponse.setBusinessKey(processInstanceHashMap.get(t.getProcessInstanceId()).getBusinessKey());
            taskResponse.setProcessStartTime(processInstanceHashMap.get(t.getProcessInstanceId()).getStartTime());
            if ("$INITIATOR".equals(t.getAssignee())) {
                taskResponse.setUserId(processInstanceHashMap.get(t.getProcessInstanceId()).getStartUserId());
            } else {
                taskResponse.setUserId(t.getAssignee());
            }
            taskResponse.setSubmitter(processInstanceHashMap.get(t.getProcessInstanceId()).getStartUserId());
            taskResponse.setTaskEchoVariables(variablesLocal);
            if (t.getCategory() != null) {
                taskResponse.setCategory(t.getCategory());
            } else {
                taskResponse.setCategory("");
            }
            List<String> userLists = currentAssigneeMap.get(taskResponse.getProcessInstanceId());
            if (CollectionUtils.isEmpty(userLists)) {
                taskResponse.setCurrentAssignees("-");
            } else {
                HashSet<String> userSet = new HashSet<>(userLists);
                taskResponse.setCurrentAssignees(StringUtils.join(userSet, ","));
            }
            return taskResponse;
        }).collect(Collectors.toList());
    }

    /**
     * 获取已办列表
     *
     * @param historicTaskInstanceList
     * @return
     */
    private List<TaskResponse> getDoneTaskResponses(List<HistoricTaskInstance> historicTaskInstanceList) {
        if (CollectionUtils.isEmpty(historicTaskInstanceList)) {
            return new ArrayList<>(0);
        }

        Set<String> processInstanceIds = historicTaskInstanceList.stream()
                .map(HistoricTaskInstance::getProcessInstanceId)
                .collect(Collectors.toSet());
        Set<String> doneTaskIds = historicTaskInstanceList.stream()
                .map(HistoricTaskInstance::getId)
                .collect(Collectors.toSet());
        List<HistoricProcessInstance> historicProcessInstanceList = historyService
                .createHistoricProcessInstanceQuery()
                .processInstanceIds(processInstanceIds)
                .list();
        Map<String, HistoricProcessInstance> historicProcessInstanceMap = historicProcessInstanceList.stream()
                .collect(Collectors.toMap(HistoricProcessInstance::getId, h -> h));

        List<HistoricVariableInstance> historicVariableInstanceList = historyService.createHistoricVariableInstanceQuery()
                .taskIds(doneTaskIds)
                .list();
        HashMap<String, Map<String, Object>> tmpMap = Maps.newHashMap();
        for (HistoricVariableInstance historicVariableInstance : historicVariableInstanceList) {
            if (historicVariableInstance.getTaskId() != null) {
                Map<String, Object> historicVariableMap = tmpMap.get(historicVariableInstance.getTaskId());
                if (historicVariableMap == null) {
                    historicVariableMap = new HashMap<>();
                }
                historicVariableMap.put(historicVariableInstance.getVariableName(), historicVariableInstance.getValue());
                tmpMap.put(historicVariableInstance.getTaskId(), historicVariableMap);
            }
        }
        //查询流程当前审批人
        Map<String, List<String>> currentAssigneeMap = getProcessCurrentUser(new ArrayList<>(processInstanceIds));

        return historicTaskInstanceList.parallelStream().map(t -> {
            TaskResponse taskResponse = new TaskResponse();
            taskResponse.setTaskId(t.getId());
            taskResponse.setProcessInstanceId(t.getProcessInstanceId());
            taskResponse.setTaskName(t.getName());
            taskResponse.setTaskDefinitionKey(t.getTaskDefinitionKey());
            taskResponse.setDescription(t.getDescription());
            if (CollectionUtils.isEmpty(currentAssigneeMap.get(t.getProcessInstanceId()))) {
                taskResponse.setCurrentAssignees("-");
            } else {
                List<String> strings = currentAssigneeMap.get(t.getProcessInstanceId());
                taskResponse.setCurrentAssignees(StringUtils.join(strings, ","));
            }
            taskResponse.setTaskCreateTime(t.getCreateTime());
            taskResponse.setProcessDefinitionKey(historicProcessInstanceMap.get(t.getProcessInstanceId()).getProcessDefinitionKey());
            taskResponse.setTaskEndTime(t.getEndTime());
            Map<String, Object> taskEchoVariables = tmpMap.get(t.getId());

            if(taskEchoVariables!=null && taskEchoVariables.get("childVariable")!=null){
                Object childVariable = taskEchoVariables.get("childVariable");
                JSONObject jsonObject = JSON.parseObject(childVariable.toString());
                String processInstanceName = jsonObject.getString("processInstanceName");
                if(StringUtils.isBlank(processInstanceName)){
                    processInstanceName="";
                }
                taskResponse.setProcessInstanceName(historicProcessInstanceMap.get(t.getProcessInstanceId()).getName()+
                        "（"+processInstanceName+"）");
            }else {
                taskResponse.setProcessInstanceName(historicProcessInstanceMap.get(t.getProcessInstanceId()).getName());
            }
            taskResponse.setBusinessKey(historicProcessInstanceMap.get(t.getProcessInstanceId()).getBusinessKey());
            taskResponse.setProcessStartTime(historicProcessInstanceMap.get(t.getProcessInstanceId()).getStartTime());
            taskResponse.setUserId(t.getAssignee());
            taskResponse.setSubmitter(historicProcessInstanceMap.get(t.getProcessInstanceId()).getStartUserId());
            taskResponse.setTaskEchoVariables(taskEchoVariables);
            if (t.getCategory() != null) {
                taskResponse.setCategory(t.getCategory());
            } else {
                taskResponse.setCategory("");
            }
            return taskResponse;
        }).collect(Collectors.toList());
    }

    /**
     * 获取当前流程的所有审批人信息
     *
     * @param processInstanceIds
     * @return
     */
    private Map<String, List<String>> getProcessCurrentUser(List<String> processInstanceIds) {
        List<Task> list = taskService.createTaskQuery().processInstanceIdIn(processInstanceIds).list();
        Map<String, List<String>> currentAssigneeMap = new HashMap<>();
        for (Task task : list) {
            List<String> strings = currentAssigneeMap.get(task.getProcessInstanceId());
            if (CollectionUtils.isEmpty(strings)) {
                strings = new ArrayList<>();
            }
            strings.add(task.getAssignee());
            currentAssigneeMap.put(task.getProcessInstanceId(), strings);
        }
        return currentAssigneeMap;
    }

    /**
     * 查询历史线
     *
     * @param processInstanceId
     * @return
     */
    public List<ActivityInstance> getHistoryFlowSequence(String processInstanceId) {
        List<ActivityInstance> list = runtimeService.createActivityInstanceQuery()
                .processInstanceId(processInstanceId)
                .finished()
                .orderByActivityInstanceEndTime()
                .desc()
                .activityType(BpmnXMLConstants.ELEMENT_SEQUENCE_FLOW)
                .list();
        return list;
    }

    public void addUserFilter(String processInstanceId, String userCode) {
        List<ActivityInstance> historyFlowSequence = getHistoryFlowSequence(processInstanceId);
        if (CollectionUtils.isEmpty(historyFlowSequence)) {
            return;
        }
        FilterUser filterUser = new FilterUser();
        filterUser.setFlowableInstanceId(processInstanceId);
        filterUser.setAgreeUserCode(userCode);
        filterUser.setFlowableTaskKey(historyFlowSequence.get(0).getActivityId());
        filterUserService.saveAgreeUser(filterUser);
    }

    public TaskResponse getTaskInfoByTaskId(String taskId) {

        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        TaskResponse taskResponse = new TaskResponse();
        if (task == null) {
            HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery().taskId(taskId).singleResult();
            Map<String, Object> taskLocalVariables = historicTaskInstance.getTaskLocalVariables();
            List<TaskResponse> doneTaskResponses = getDoneTaskResponses(Collections.singletonList(historicTaskInstance));
            if (CollectionUtils.isEmpty(doneTaskResponses)) {
                return taskResponse;
            } else {
                return doneTaskResponses.get(0);
            }
        }
        List<TaskResponse> taskResponses = getTaskResponses(Collections.singletonList(task));
        if (CollectionUtils.isEmpty(taskResponses)) {
            return taskResponse;
        }else{
            return taskResponses.get(0);
        }
    }

    public long getTaskCountByUserId(String userId) {
        return taskService.createTaskQuery()
                .taskAssignee(userId).count();
    }

    public TaskResponse getCurrentTaskDefinitionInfo(String businessKey, String processDefinitionKey) {
        List<Task> list = taskService.createTaskQuery().processInstanceBusinessKey(businessKey)
                .processDefinitionKey(processDefinitionKey).active().list();
        TaskResponse taskResponse = new TaskResponse();
        if (CollectionUtils.isEmpty(list)) {
            return taskResponse;
        }
        Task task = list.get(0);
        taskResponse.setTaskName(task.getName());
        taskResponse.setDescription(task.getDescription());
        taskResponse.setTaskDefinitionKey(task.getTaskDefinitionKey());
        taskResponse.setProcessInstanceId(task.getProcessInstanceId());
        return taskResponse;
    }


    public List<PorcessResponse> getTaskListByBusinessId(String businessKey, String processDefinitionKey) {
        List<HistoricProcessInstance> list = historyService.createHistoricProcessInstanceQuery()
                .processInstanceBusinessKey(businessKey)
                .processDefinitionKey(processDefinitionKey)
                .orderByProcessInstanceEndTime()
                .asc()
                .list();
        List<PorcessResponse> porcessResponses = Lists.newArrayList();
        for (HistoricProcessInstance historicProcessInstance : list) {
            PorcessResponse porcessResponse = new PorcessResponse();
            porcessResponse.setProcessInstanceId(historicProcessInstance.getId());
            porcessResponse.setProcessDefinitionKey(historicProcessInstance.getProcessDefinitionKey());
            porcessResponse.setBusinessKey(historicProcessInstance.getBusinessKey());
            porcessResponse.setProcessInstanceName(historicProcessInstance.getName());
            porcessResponse.setEndTime(historicProcessInstance.getEndTime());
            porcessResponse.setStartTime(historicProcessInstance.getStartTime());
            porcessResponse.setProcessStartUserId(historicProcessInstance.getStartUserId());
            if (historicProcessInstance.getEndTime() != null) {
                porcessResponse.setStatus(FLOWSTATUS.SUCCESS_END);
            } else {
                porcessResponse.setStatus(FLOWSTATUS.ACTIVE);
            }
            porcessResponses.add(porcessResponse);
        }
        return porcessResponses;
    }

    public PorcessResponse getProcessInstanceByProcessInstanceId(String processInstanceId) {
        HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
                .processInstanceId(processInstanceId)
                .singleResult();
        if (historicProcessInstance == null) {
            return null;
        } else {
            return convertToPorcessResponse(historicProcessInstance);
        }
    }

    /**
     * 根据业务主键和流程定义可能会查到历史，所以仅限于查询未结束的流程
     * 结束流程请用
     * @param businessId
     * @param processDefinitionKey
     * @return
     */
    public PorcessResponse getProcessInstanceByBusinessIdAndProcessDefinitionKey(String businessId, String processDefinitionKey) {
        HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
                .processInstanceBusinessKey(businessId)
                .processDefinitionKey(processDefinitionKey)
                .unfinished()
                .singleResult();
        if (historicProcessInstance == null) {
            return null;
        } else {
            return convertToPorcessResponse(historicProcessInstance);
        }
    }

    private PorcessResponse convertToPorcessResponse(HistoricProcessInstance historicProcessInstance) {

        List<HistoricVariableInstance> list = historyService.createHistoricVariableInstanceQuery()
                .processInstanceId(historicProcessInstance.getId()).list();
        Map<String, Object> variables = new HashMap<>();
        for (HistoricVariableInstance historicVariableInstance : list) {
            variables.put(historicVariableInstance.getVariableName(),historicVariableInstance.getValue());
        }
        PorcessResponse porcessResponse = new PorcessResponse();
        porcessResponse.setProcessInstanceId(historicProcessInstance.getId());
        porcessResponse.setProcessDefinitionKey(historicProcessInstance.getProcessDefinitionKey());
        porcessResponse.setBusinessKey(historicProcessInstance.getBusinessKey());
        porcessResponse.setProcessInstanceName(historicProcessInstance.getName());
        porcessResponse.setEndTime(historicProcessInstance.getEndTime());
        porcessResponse.setStartTime(historicProcessInstance.getStartTime());
        porcessResponse.setProcessStartUserId(historicProcessInstance.getStartUserId());
        porcessResponse.setRouterVariables(variables);
        if (historicProcessInstance.getEndTime() != null) {
            porcessResponse.setStatus(FLOWSTATUS.SUCCESS_END);
        } else {
            porcessResponse.setStatus(FLOWSTATUS.ACTIVE);
        }
        return porcessResponse;
    }

    public String deleteProcessInstanceByProcessDefinitionKey(String processDefinitionKey) {

        List<HistoricProcessInstance> unfinishedList = historyService.createHistoricProcessInstanceQuery().processDefinitionKey(processDefinitionKey).unfinished().list();
        for (HistoricProcessInstance historicProcessInstance : unfinishedList) {
            runtimeService.deleteProcessInstance(historicProcessInstance.getId(),"");
        }
        List<HistoricProcessInstance> finishedList = historyService.createHistoricProcessInstanceQuery().processDefinitionKey(processDefinitionKey).finished().list();
        for (HistoricProcessInstance historicProcessInstance : finishedList) {
            historyService.deleteHistoricProcessInstance(historicProcessInstance.getId());
        }
        return "success";
    }

    /**
     * 修改消息为已办状态
     * @param taskId
     */
    private void changeToDoneMessage(String taskId){
        // 2022/12/27 对接修改状态接口
        try {
            String url = eamMessageChangeUrl+"?businessId="+taskId;
            httpUtil.get(url);
        }catch (Exception e){
            log.error("消息修改状态失败：",e);
        }

    }

    /**
     * 对接新增消息接口
     * @param taskList
     */
    private void sendTaskMessage(List<Task> taskList, Boolean startProcess){
        try {
            List<TaskResponse> taskResponses = getTaskResponses(taskList);
            List<WorkBenchMessageDto> workBenchMessageDtos = new ArrayList<>();
            for (TaskResponse taskRespons : taskResponses) {
                WorkBenchMessageDto workBenchMessageDto = new WorkBenchMessageDto();
                BeanUtils.copyProperties(taskRespons,workBenchMessageDto);
                workBenchMessageDto.setStartProcess(startProcess);
                workBenchMessageDtos.add(workBenchMessageDto);
                if (viewProcessDefineKey.equals(taskRespons.getProcessDefinitionKey()) || GT_DIAGRAM_APPROVE.equals(taskRespons.getProcessDefinitionKey())) {
                    workBenchMessageDto.setType(3);
                }else if(PLAN_DEFINITION_KEY1.equals(taskRespons.getProcessDefinitionKey()) || planProcessDefineKey.equals(taskRespons.getProcessDefinitionKey())){
                    workBenchMessageDto.setType(1);
                } else if (MODEL_DEFINITION_KEY.equals(taskRespons.getProcessDefinitionKey())) {
                    workBenchMessageDto.setType(4);
                } else if (XW_BUSINESS_SCENARIO_APPROVE.equals(taskRespons.getProcessDefinitionKey())) {
                    Map<String, Object> taskEchoVariables = taskRespons.getTaskEchoVariables();
                    if (CollectionUtils.isEmpty(taskEchoVariables)) {
                        workBenchMessageDto.setType(1);
                    } else {
                        Object childVariable = taskEchoVariables.get("childVariable");
                        if (!org.springframework.util.StringUtils.isEmpty(childVariable)) {
                            JSONObject jsonObject = JSON.parseObject(childVariable.toString());
                            String childBusinessKey = jsonObject.getString("childBusinessKey");
                            workBenchMessageDto.setBusinessKey(childBusinessKey);
                            workBenchMessageDto.setType(4);

                        }else {
                            workBenchMessageDto.setType(1);
                        }
                    }
                } else if (GT_TECHNICAL_SCHEME_APPROVE.equals(taskRespons.getProcessDefinitionKey())) {
                    workBenchMessageDto.setType(5);
                    Map<String, Object> taskEchoVariables = taskRespons.getTaskEchoVariables();
                    if (!CollectionUtils.isEmpty(taskEchoVariables)) {
                        Object childVariable = taskEchoVariables.get("childVariable");
                        if (!org.springframework.util.StringUtils.isEmpty(childVariable)) {
                            JSONObject jsonObject = JSON.parseObject(childVariable.toString());
                            String childBusinessKey = jsonObject.getString("childBusinessKey");
                            workBenchMessageDto.setGtChildBusinessKey(childBusinessKey);
                        }
                    }
                } else if (GT_ASSERT_APPROVE.equals(taskRespons.getProcessDefinitionKey())) {
                    workBenchMessageDto.setType(7);
                }
                workBenchMessageDto.setAction(1);
                workBenchMessageDto.setTaskEchoVariables(taskRespons.getTaskEchoVariables());
                workBenchMessageDto.setBusinessId(workBenchMessageDto.getTaskId());
                if ("rectification".equals(workBenchMessageDto.getDescription())) {
                    workBenchMessageDto.setUserId(workBenchMessageDto.getSubmitter());
                }
            }
            String postResponse = httpUtil.post(eamMessageSaveUrl, workBenchMessageDtos);
            log.info("发送消息响应：{}", postResponse);
        } catch (Exception e) {
            log.error("消息发送失败：", e);
        }
    }

    public TaskResponse getCurrentUserTask(String businessKey, String processDefinitionKey, String userCode) {
        Task task = taskService.createTaskQuery().processInstanceBusinessKey(businessKey)
                .processDefinitionKey(processDefinitionKey).taskAssignee(userCode).singleResult();
        TaskResponse taskResponse = new TaskResponse();
        if (task == null) {
            return taskResponse;
        }
        taskResponse.setTaskId(task.getId());
        taskResponse.setTaskName(task.getName());
        taskResponse.setDescription(task.getDescription());
        taskResponse.setTaskDefinitionKey(task.getTaskDefinitionKey());
        taskResponse.setProcessInstanceId(task.getProcessInstanceId());
        return taskResponse;
    }

    public TaskResponse getCurrentUserActiveTask(String businessKey, String processDefinitionKey, String userCode) {
        Task task = taskService.createTaskQuery().processInstanceBusinessKey(businessKey)
                .processDefinitionKey(processDefinitionKey).taskAssignee(userCode).active().singleResult();
        TaskResponse taskResponse = new TaskResponse();
        if (task == null) {
            return taskResponse;
        }
        taskResponse.setTaskId(task.getId());
        taskResponse.setTaskName(task.getName());
        taskResponse.setDescription(task.getDescription());
        taskResponse.setTaskDefinitionKey(task.getTaskDefinitionKey());
        taskResponse.setProcessInstanceId(task.getProcessInstanceId());
        return taskResponse;
    }

    public List<TaskResponse> getActiveTaskByProcessInstanceId(String processInstanceId) {
        List<Task> list = taskService.createTaskQuery().processInstanceId(processInstanceId).active().list();
        return getTaskResponses(list);
    }


    public void terminateProcessInstanceById(String processInstanceId, String terminationReason) {
        runtimeService.deleteProcessInstance(processInstanceId,terminationReason);
    }

    public TaskResponse getCurrentOwnerTask(String businessKey, String userCode) {
        Task task = taskService.createTaskQuery().processInstanceBusinessKey(businessKey).taskAssignee(userCode).singleResult();
        TaskResponse taskResponse = new TaskResponse();
        if (task == null) {
            return taskResponse;
        }
        taskResponse.setTaskId(task.getId());
        taskResponse.setTaskName(task.getName());
        taskResponse.setDescription(task.getDescription());
        taskResponse.setTaskDefinitionKey(task.getTaskDefinitionKey());
        taskResponse.setProcessInstanceId(task.getProcessInstanceId());
        return taskResponse;
    }

    public Boolean selectFlowStatus(String businessKey, String processDefinitionKey) {
        List<Terminate> terminates = terminateService.selectFlowStatus(businessKey, processDefinitionKey);
        if(CollectionUtils.isEmpty(terminates)){
            log.info("##########当前流程在审批流程中，可点击查看");
            return false;
        }
        log.info("##########当前流程已被终止,流程已结束，不可查看：【{}】",terminates.get(0));
        return true;
    }

    public List<TaskResponse> getDoneAllTask() {
        List<HistoricTaskInstance> historicTaskInstanceList = historyService.createHistoricTaskInstanceQuery()
                .orderByHistoricTaskInstanceEndTime()
                .taskVariableValueLikeIgnoreCase("pass", "%a%")
                .finished()
                .desc().list();
        return getDoneTaskResponses(historicTaskInstanceList);
    }

    public List<TaskResponse> getCurrentAllTask() {
        List<Task> list = taskService.createTaskQuery()
                .orderByTaskCreateTime()
                .desc().list();
        List<TaskResponse> taskResponses = getTaskResponses(list);
        return taskResponses;

    }

    public Boolean isExistByTaskId(String taskId) {
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        if (task == null) {
            return Boolean.FALSE;
        }
        return Boolean.TRUE;
    }

    public void suspendedTask(String taskId) {
        Optional<ActRuTask> currentTask = actRuTaskRepository.findById(taskId);
        if (currentTask.isPresent()) {
            ActRuTask actRuTask = currentTask.get();
            actRuTask.setSuspensionState(SuspensionState.SUSPENDED.getStateCode());
            actRuTaskRepository.saveAndFlush(actRuTask);
        }
    }

    public void changeAssigness(TaskRequest request) {
        taskService.setAssignee(request.getTaskId(), request.getUserId());
    }

    public void delegateTask(TaskRequest request) {
        taskService.delegateTask(request.getTaskId(), request.getUserId());
    }

    public void resolveTask(String taskId) {
        taskService.resolveTask(taskId);
    }

    public List<TaskResponse> listForArchReview(ArchReviewTaskQueryReq req) {
        if (req.getType() == 1) {
            return queryTaskByActiveDescriptions(req.getActiveDescriptions());
        }
        if (StringUtils.isBlank(req.getAssignee())) {
            return new ArrayList<>();
        }
        if (req.getType() == 2) {
            List<Task> list = taskService.createTaskQuery().processDefinitionKey(GT_TECHNICAL_SCHEME_APPROVE)
                    .taskAssignee(req.getAssignee()).active().list();
            return getTaskResponses(list);
        }
        if (req.getType() == 3) {
            if (StringUtils.isBlank(req.getAssignee())) {
                return new ArrayList<>();
            }
            List<HistoricTaskInstance> historicTaskInstanceList = historyService.createHistoricTaskInstanceQuery()
                    .processDefinitionKey(GT_TECHNICAL_SCHEME_APPROVE)
                    .taskAssignee(req.getAssignee())
                    .orderByHistoricTaskInstanceEndTime()
                    .asc()
                    .finished()
                    .list();
            //需要过滤掉退回至申请人节点--申请人重新提交不算审批人
            List<String> filterDescription = Arrays.asList("startUserSubmit","orgCountersignReject","orgOrSignReject","preReviewRotaReject","preReviewExpertReject",
                    "preReviewFinalExpertReject","pmoReject");
            List<HistoricTaskInstance> filterList = historicTaskInstanceList.stream()
                    .filter(e -> StringUtils.isNotBlank(e.getDescription()))
                    .filter(e -> !filterDescription.contains(e.getDescription())).collect(Collectors.toList());
            return getDoneTaskResponses(filterList);
        }
        return new ArrayList<>();
    }

    private List<TaskResponse> queryTaskByActiveDescriptions(List<String> activeDescriptions) {
        if (CollectionUtils.isEmpty(activeDescriptions)) {
            return new ArrayList<>();
        }
        List<TaskResponse> responses = new ArrayList<>();
        for (String description : activeDescriptions) {
            List<Task> list = taskService.createTaskQuery()
                    .processDefinitionKey(GT_TECHNICAL_SCHEME_APPROVE)
                    .taskDescription(description).active().list();
            if (!CollectionUtils.isEmpty(list)) {
                responses.addAll(getTaskResponses(list));
            }
        }
        return responses;
    }

    public List<TaskResponse> listForDiagram(DiagramReviewTaskQueryReq req){

        if (req.getType() == 1) {
            List<String> stages = req.getStages();
            if (CollectionUtils.isEmpty(stages)) {
                return new ArrayList<>();
            }
            List<TaskResponse> responses = new ArrayList<>();
            for (String stage : stages) {
                List<Task> list = taskService.createTaskQuery()
                        .processDefinitionKey(GT_DIAGRAM_APPROVE)
                        .taskName(stage).active().list();
                if (!CollectionUtils.isEmpty(list)) {
                    responses.addAll(getTaskResponses(list));
                }
            }
            return responses;
        }
        if (StringUtils.isBlank(req.getAssignee())) {
            return new ArrayList<>();
        }
        if (req.getType() == 2) {
            List<Task> list = taskService.createTaskQuery().processDefinitionKey(GT_DIAGRAM_APPROVE)
                    .taskAssignee(req.getAssignee()).active().list();
            return getTaskResponses(list);
        }
        if (req.getType() == 3) {
            if (StringUtils.isBlank(req.getAssignee())) {
                return new ArrayList<>();
            }
            List<HistoricTaskInstance> historicTaskInstanceList = historyService.createHistoricTaskInstanceQuery()
                    .processDefinitionKey(GT_DIAGRAM_APPROVE)
                    .taskAssignee(req.getAssignee())
                    .orderByHistoricTaskInstanceEndTime()
                    .asc()
                    .finished()
                    .list();
            List<HistoricTaskInstance> filterList = historicTaskInstanceList.stream()
                    .filter(e -> StringUtils.isNotBlank(e.getDescription()))
                    .filter(e -> !"退回至申请人".equals(e.getName())).collect(Collectors.toList());
            return getDoneTaskResponses(filterList);
        }
        return new ArrayList<>();
    }


    public List<AllDiagramInstanceDto> getAllDiagramInstance() {
        List<AllDiagramInstanceDto> result = new ArrayList<>();
        // 正在运行的流程实例
        List<ProcessInstance> activeProcessInstances = runtimeService.createProcessInstanceQuery().processDefinitionKey(GT_DIAGRAM_APPROVE).list();
        for (ProcessInstance activeProcessInstance : activeProcessInstances) {
            AllDiagramInstanceDto allDiagramInstanceDto = new AllDiagramInstanceDto();
            allDiagramInstanceDto.setProcessInstanceId(activeProcessInstance.getId());
            allDiagramInstanceDto.setBusinessKey(activeProcessInstance.getBusinessKey());
            allDiagramInstanceDto.setStartUserId(activeProcessInstance.getStartUserId());
            allDiagramInstanceDto.setProcessName(activeProcessInstance.getName());
            allDiagramInstanceDto.setStartTime(activeProcessInstance.getStartTime());
            // 评审中
            allDiagramInstanceDto.setState("REVIEWING");
            result.add(allDiagramInstanceDto);
        }
        // 获取历史流程实例（已完成或被终止）
        List<HistoricProcessInstance> historicInstances = historyService.createHistoricProcessInstanceQuery()
                .processDefinitionKey(GT_DIAGRAM_APPROVE)
                .finished()
                .list();
        for (HistoricProcessInstance historicProcessInstance : historicInstances) {
            // 如果流程中有终止节点，则流程被终止
            if(historicProcessInstance.getDeleteReason() != null && historicProcessInstance.getDeleteReason().contains("terminate end event")){
                // 最后一个节点是通过，证明流程通过
                AllDiagramInstanceDto allDiagramInstanceDto = new AllDiagramInstanceDto();
                allDiagramInstanceDto.setProcessInstanceId(historicProcessInstance.getId());
                allDiagramInstanceDto.setBusinessKey(historicProcessInstance.getBusinessKey());
                allDiagramInstanceDto.setStartUserId(historicProcessInstance.getStartUserId());
                allDiagramInstanceDto.setProcessName(historicProcessInstance.getName());
                allDiagramInstanceDto.setEndTime(historicProcessInstance.getEndTime());
                allDiagramInstanceDto.setStartTime(historicProcessInstance.getStartTime());
                // 终止
                allDiagramInstanceDto.setState("TERM");
                result.add(allDiagramInstanceDto);
            }else {
                AllDiagramInstanceDto allDiagramInstanceDto = new AllDiagramInstanceDto();
                allDiagramInstanceDto.setProcessInstanceId(historicProcessInstance.getId());
                allDiagramInstanceDto.setBusinessKey(historicProcessInstance.getBusinessKey());
                allDiagramInstanceDto.setStartUserId(historicProcessInstance.getStartUserId());
                allDiagramInstanceDto.setProcessName(historicProcessInstance.getName());
                allDiagramInstanceDto.setEndTime(historicProcessInstance.getEndTime());
                allDiagramInstanceDto.setStartTime(historicProcessInstance.getStartTime());
                // 通过
                allDiagramInstanceDto.setState("PASS");
                result.add(allDiagramInstanceDto);
            }
        }
        return result;
    }

    public List<TaskResponse> queryActiveTaskByProcIdAndDes(ActiveTaskQueryReq req) {
        if (req == null || StringUtils.isBlank(req.getProcessInstanceId())
                || CollectionUtils.isEmpty(req.getDescriptions())) {
            return new ArrayList<>();
        }
        List<TaskResponse> responses = new ArrayList<>();
        for (String description : req.getDescriptions()) {
            List<Task> list = taskService.createTaskQuery()
                    .processDefinitionKey(GT_TECHNICAL_SCHEME_APPROVE)
                    .processInstanceId(req.getProcessInstanceId())
                    .taskDescription(description).active().list();
            if (!CollectionUtils.isEmpty(list)) {
                responses.addAll(getTaskResponses(list));
            }
        }
        return responses;
    }

    public List<TaskResponse> getActiveSimpleTaskByProcessInstanceIds(List<String> processInstanceIds) {
        List<Task> list = taskService.createTaskQuery().processInstanceIdIn(processInstanceIds).active().list();
        return list.stream().filter(tt -> !tt.isSuspended()).parallel().map(t -> {
            TaskResponse taskResponse = new TaskResponse();
            taskResponse.setTaskId(t.getId());
            taskResponse.setProcessInstanceId(t.getProcessInstanceId());
            taskResponse.setTaskDefinitionKey(t.getTaskDefinitionKey());
            taskResponse.setDescription(t.getDescription());
            taskResponse.setTaskCreateTime(t.getCreateTime());
            taskResponse.setTaskName(t.getName());
            return taskResponse;
        }).collect(Collectors.toList());
    }
}
